﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net.Sockets;
using System.Net;
using System.Collections;
using System.Net.Security;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Timers;
using System.ComponentModel;

namespace CommunicationServer
{
    [Serializable]
    public class TCPServerMemberCredentials
    {
        #region Properties
        public string UserName { get; set; }
        public string Password { get; set; }
        #endregion

        #region Constructors
        public TCPServerMemberCredentials()
        {
        }
        public TCPServerMemberCredentials(string UserName)
        {
            this.UserName = UserName;
        }
        public TCPServerMemberCredentials(string UserName, string Password)
        {
            this.UserName = UserName;
            this.Password = Password;
        }
        #endregion
    }

    public static class TCPServerHelper
    {
        #region Public Methods
        public static TCPServerMember GetMember(ref TCPServer Server, int MemberHashCode)
        {
            // Define TCPServerMember object
            TCPServerMember tsmMember = null;
            // Check if member hash code exists
            if (Server.hshMembers.ContainsKey(MemberHashCode))
            {
                // Set member to TCPServerMember object
                tsmMember = (TCPServerMember)Server.hshMembers[MemberHashCode];
            }
            // Return
            return tsmMember;
        }
        public static TCPServerMember[] GetMembers(ref TCPServer Server)
        {
            // Create TCPServerMember array
            TCPServerMember[] tsmMembers = new TCPServerMember[Server.hshMembers.Count];
            // Copy hashtable items to tsmMembers array            
            Server.hshMembers.Values.CopyTo(tsmMembers, 0);
            // Return
            return tsmMembers;
        }
        public static TCPServerMember[] GetMembersByCredential(ref TCPServer Server, TCPServerMemberCredentials MemberCredential)
        {
            // Create arraylist for matched connections
            ArrayList arlMemberHashCodes = new ArrayList();
            // Find matched connections
            int[] intMemberHashCodes = TCPServerHelper.GetMemberHashCodes(ref Server.hshMembers);
            // Find mathes and add to arraylist
            foreach (int intMemberHashCode in intMemberHashCodes)
            {
                if (((TCPServerMember)Server.hshMembers[intMemberHashCode]).MemberCredential.UserName == MemberCredential.UserName)
                {
                    arlMemberHashCodes.Add((TCPServerMember)Server.hshMembers[intMemberHashCode]);
                }
            }
            // Copy arraylist to array
            TCPServerMember[] tsmMembers = (TCPServerMember[])arlMemberHashCodes.ToArray(typeof(TCPServerMember));
            // Release arraylist
            arlMemberHashCodes.Clear();
            // Return
            return tsmMembers;
        }
        #endregion

        #region Internal Methods
        internal static int[] GetMemberHashCodes(ref Hashtable MemberArray)
        {
            // Define return variable
            int[] intMembers = new int[MemberArray.Count];
            // Fill members to array
            IEnumerator enumMemberHashKeys = MemberArray.Keys.GetEnumerator();
            int intMemberIndex = 0;
            while (enumMemberHashKeys.MoveNext())
            {
                int intHashKey = (int)enumMemberHashKeys.Current;
                intMembers[intMemberIndex] = ((TCPServerMember)MemberArray[intHashKey]).GetHashCode();
                intMemberIndex++;
            }
            // Return Members
            return intMembers;
        }
        #endregion
    }

    public class TCPServerMember : IDisposable
    {
        #region Variables
        #region Events
        // Event fires when a message is received through network
        internal delegate void MemberMessageDelegate(TCPServerMember sender, string Message);
        internal event MemberMessageDelegate MessageReceived;

        // Event fires when an authentication message is received through network
        internal delegate void MemberAuthenticationMessageReceivedDelegate(TCPServerMember sender, TCPServerMemberCredentials e);
        internal event MemberAuthenticationMessageReceivedDelegate AuthenticationMessageReceived;

        // Event fires when a connection is terminated
        internal delegate void ConnectionTerminatedDelegate(TCPServerMember sender);
        internal event ConnectionTerminatedDelegate ConnectionTerminated;
        #endregion

        #region Streams
        // Network stream that handles message transfer
        private NetworkStream _NetworkStream;
        #endregion

        #region Properties
        // Bool value to define member is authenticated with TCPServerMemberCredentials
        private bool _IsAuthenticated = false;
        // TCPServerMemberCredential information for this TCPServerMember class
        private TCPServerMemberCredentials _MemberCredential = new TCPServerMemberCredentials();
        // IPEndPoint property for TCPServerMember
        private IPEndPoint _MemberIPEndPoint;
        // Auhtentication timeout
        private double _AuthenticationTimeout = 1000;
        // Text Encoding
        private Encoding _TextEncoding = System.Text.Encoding.UTF8;
        #endregion

        #region Timers
        // Timer for authentication timeout
        private Timer tmrAuthenticationTimeout = new Timer();
        #endregion
        #endregion

        #region Constructors
        public TCPServerMember()
        {
            // Set authentication timeout timer
            this.tmrAuthenticationTimeout.Interval = this.AuthenticationTimeout;
            this.tmrAuthenticationTimeout.Elapsed += new ElapsedEventHandler(tmrAuthenticationTimeout_Elapsed);
            this.tmrAuthenticationTimeout.Enabled = true;
            this.tmrAuthenticationTimeout.Start();
        }
        #endregion

        #region Properties
        internal NetworkStream NetworkStream
        {
            get { return _NetworkStream; }
            set { _NetworkStream = value; }
        }
        public bool IsAuthenticated
        {
            get { return _IsAuthenticated; }
            set { _IsAuthenticated = value; }
        }
        public TCPServerMemberCredentials MemberCredential
        {
            get { return _MemberCredential; }
            internal set { _MemberCredential = value; }
        }
        public IPEndPoint MemberIPEndPoint
        {
            get { return this._MemberIPEndPoint; }
            internal set { this._MemberIPEndPoint = value; }
        }
        public double AuthenticationTimeout
        {
            get { return this._AuthenticationTimeout; }
            set { this._AuthenticationTimeout = value; }
        }
        public Encoding TextEncoding
        {
            get { return this._TextEncoding; }
            set { this._TextEncoding = value; }
        }
        #endregion

        #region Thread Safe Event Raisers
        private void RaiseConnectionTerminatedEvent(TCPServerMember sender)
        {
            // Check if delegate is assigned
            if (ConnectionTerminated != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = ConnectionTerminated.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(ConnectionTerminated, new object[] { sender });
                }
                else
                {
                    // Raise the event
                    ConnectionTerminated.Invoke(sender);
                }
            }
        }
        private void RaiseAuthenticationMessageReceivedEvent(TCPServerMember sender, TCPServerMemberCredentials e)
        {
            // Check if delegate is assigned
            if (AuthenticationMessageReceived != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = AuthenticationMessageReceived.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(AuthenticationMessageReceived, new object[] { sender, e });
                }
                else
                {
                    // Raise the event
                    AuthenticationMessageReceived.Invoke(sender, e);
                }
            }
        }
        private void RaiseMessageReceivedEvent(TCPServerMember sender, string Message)
        {
            // Check if delegate is assigned
            if (MessageReceived != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = MessageReceived.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(MessageReceived, new object[] { sender, Message });
                }
                else
                {
                    // Raise the event
                    MessageReceived.Invoke(sender, Message);
                }
            }
        }
        #endregion

        #region Public Methods
        public bool SendMessage(string Message)
        {
            try
            {
                // Check if network stream is null
                if (this.NetworkStream != null)
                {
                    // Check if network stream can write data
                    if (this.NetworkStream.CanWrite)
                    {
                        // Convert message to byte array
                        byte[] bytData = this.TextEncoding.GetBytes(Message);
                        // Invoke BeginWrite method and write data to network
                        this.NetworkStream.BeginWrite(bytData, 0, bytData.Length, new AsyncCallback(SendingMessage), this.NetworkStream);
                        // Return
                        return true;
                    }
                }
            }
            catch
            {
            }
            return false;
        }
        public void Disconnect()
        {
            //Close tcpclient & network stream.
            if (this.NetworkStream != null)
            {
                this.NetworkStream.Close();
            }
            // Raise event
            this.RaiseConnectionTerminatedEvent(this);
            //this.ConnectionTerminated(this);
        }
        #endregion

        #region Internal Methods
        internal void WaitForMessages()
        {
            try
            {
                // Check if network stream is null
                if (this.NetworkStream != null)
                {
                    // Check if network stream can read data
                    if (this.NetworkStream.CanRead)
                    {
                        // Invoke BeginRead method and wait for incoming messages
                        this.NetworkStream.BeginRead(new byte[1024], 0, 0, new AsyncCallback(ClientMessageReceived), this.NetworkStream);
                    }
                }
            }
            catch (ObjectDisposedException odeExcp)
            {
                // Object is disposed
                return;
            }
        }
        #endregion

        #region Private Methods
        private void ClientMessageReceived(IAsyncResult iar)
        {
            // Define IAsyncResult network stream
            NetworkStream nsX = null;
            try
            {
                // Get network stream
                nsX = (NetworkStream)iar.AsyncState;
                // End read
                int intEndPoint = nsX.EndRead(iar);
                // Process incoming data
                if (this.IsAuthenticated)
                {
                    // Get received data
                    string strReceivedData = "";
                    while (nsX.DataAvailable)
                    {
                        byte[] bytReceivedData = new byte[1024];
                        int a = nsX.Read(bytReceivedData, 0, 1024);
                        //strReceivedData += System.Text.Encoding.ASCII.GetString(bytReceivedData);
                        strReceivedData += this.TextEncoding.GetString(bytReceivedData);
                    }
                    if (strReceivedData.Length > 0)
                    {
                        // Raise Message Received event
                        this.RaiseMessageReceivedEvent(this, strReceivedData);
                        //this.MessageReceived(this, strReceivedData); 
                    }
                    else
                    {
                        // No incoming data, the connection is lost
                        this.RaiseConnectionTerminatedEvent(this);
                        //this.ConnectionTerminated(this);
                        // Return
                        return;
                    }
                }
                else
                {
                    // Get received data
                    string strReceivedData = "";
                    while (nsX.DataAvailable)
                    {
                        byte[] bytReceivedData = new byte[1024];
                        int a = nsX.Read(bytReceivedData, 0, 1024);
                        strReceivedData += System.Text.Encoding.ASCII.GetString(bytReceivedData);
                        //strReceivedData += this.TextEncoding.GetString(bytReceivedData);
                    }
                    if (strReceivedData.Length > 0)
                    {
                        // Deserialize ManualAuhtenticationCredentials
                        // Define binary formatter
                        BinaryFormatter bnfAuth = new BinaryFormatter();
                        // Define memory stream
                        //MemoryStream mmsAuth = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(strReceivedData));
                        MemoryStream mmsAuth = new MemoryStream(this.TextEncoding.GetBytes(strReceivedData));
                        try
                        {
                            // Deserialize data to ManualAuthenticationCredentials
                            TCPServerMemberCredentials macAuth = (TCPServerMemberCredentials)bnfAuth.Deserialize(mmsAuth);
                            // Set credential information to local variable
                            this.MemberCredential.UserName = macAuth.UserName;
                            this.MemberCredential.Password = macAuth.Password;
                            // Raise event
                            this.RaiseAuthenticationMessageReceivedEvent(this, macAuth);
                            //this.AuthenticationMessageReceived(this, macAuth);
                        }
                        catch (Exception excp)
                        {
                            // Disconnect user because logon operation has failed
                            this.Disconnect();
                            // Return
                            return;
                        }
                    }
                    else
                    {
                        // No incoming data, the connection is lost
                        this.RaiseConnectionTerminatedEvent(this);
                        //this.ConnectionTerminated(this);
                        // Return
                        return;
                    }
                }
                // Continue reading
                nsX.BeginRead(new byte[1024], 0, 0, new AsyncCallback(ClientMessageReceived), nsX);
            }
            catch (ObjectDisposedException odeExcp)
            {
                // Object disposed
                return;
            }
            catch (Exception excp)
            {
                //continue reading
                try
                {
                    nsX.BeginRead(new byte[1024], 0, 0, new AsyncCallback(ClientMessageReceived), nsX);
                }
                catch
                {
                    // Can not continue so disconnect
                    this.NetworkStream.Close();
                    // Raise disconnected event
                    this.RaiseConnectionTerminatedEvent(this);
                    //this.ConnectionTerminated(this);
                }
            }
        }
        private void SendingMessage(IAsyncResult iar)
        {
            // Get network stream
            NetworkStream nstX = (NetworkStream)iar.AsyncState;
            try
            {
                // Send message asynchronously
                nstX.EndWrite(iar);
            }
            catch (ObjectDisposedException odeExcp)
            {
                // Object disposed
                return;
            }
        }
        void tmrAuthenticationTimeout_Elapsed(object sender, ElapsedEventArgs e)
        {
            // Disable Timers
            this.tmrAuthenticationTimeout.Stop();
            this.tmrAuthenticationTimeout.Enabled = false;
            this.tmrAuthenticationTimeout.Dispose();
            // Check if authentication is succeeded if not disconnect & dispose
            if (!this.IsAuthenticated)
            {
                // No authentication is done, so disconnect
                this.Disconnect();
            }
        }
        #endregion

        #region IDisposable Members
        public void Dispose()
        {
            //// Close connection
            //this.CloseConnection();
            // Dispose objects
            try
            {
                this.NetworkStream.Dispose();
            }
            catch
            {
            }
            //// Raise event
            //this.ConnectionTerminated(this);
        }
        #endregion
    }

    public class TCPServer : IDisposable
    {
        #region Variables
        #region Events
        public delegate void MessageReceivedDelegate(TCPServerMember sender, string Message);
        public event MessageReceivedDelegate MessageReceived;

        public delegate void AuthenticationMessageReceivedDelegate(TCPServerMember sender, TCPServerMemberCredentials e);
        public event AuthenticationMessageReceivedDelegate AuthenticationMessageReceived;

        public delegate void ServerStartDelegate();
        public event ServerStartDelegate ServerStart;

        public delegate void ServerStopDelegate();
        public event ServerStopDelegate ServerStop;

        public delegate void ConnectionEstablishedDelegate(TCPServerMember sender);
        public event ConnectionEstablishedDelegate ConnectionEstablished;

        public delegate void ConnectionTerminatedDelegate(TCPServerMember sender);
        public event ConnectionTerminatedDelegate ConnectionTerminated;
        #endregion

        #region TCP Objects
        private TcpListener tlsServer;
        private TcpClient tclServer;
        #endregion

        #region Properties
        private int _serverPort = 0;
        private IPAddress _serverIPAddress = new IPAddress(0);
        private double _authenticationTimeout = 1000;
        #endregion

        #region Collections
        internal Hashtable hshMembers = new Hashtable();
        #endregion
        #endregion

        #region Properties
        public int ServerPort
        {
            get { return _serverPort; }
            set { _serverPort = value; }
        }
        public IPAddress ServerIPAddress
        {
            get { return _serverIPAddress; }
            set { _serverIPAddress = value; }
        }
        public double AuthenticationTimeout
        {
            get { return this._authenticationTimeout; }
            set { this._authenticationTimeout = value; }
        }
        #endregion

        #region Thread Safe Event Raisers
        private void RaiseConnectionTerminatedEvent(TCPServerMember sender)
        {
            // Check if delegate is assigned
            if (ConnectionTerminated != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = ConnectionTerminated.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(ConnectionTerminated, new object[] { sender });
                }
                else
                {
                    // Raise the event
                    ConnectionTerminated.Invoke(sender);
                }
            }
        }
        private void RaiseConnectionEstablishedEvent(TCPServerMember sender)
        {
            // Check if delegate is assigned
            if (ConnectionEstablished != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = ConnectionEstablished.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(ConnectionEstablished, new object[] { sender });
                }
                else
                {
                    // Raise the event
                    ConnectionEstablished.Invoke(sender);
                }
            }
        }
        private void RaiseServerStopEvent()
        {
            // Check if delegate is assigned
            if (ServerStop != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = ServerStop.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(ServerStop, new object[] { });
                }
                else
                {
                    // Raise the event
                    ServerStop.Invoke();
                }
            }
        }
        private void RaiseServerStartEvent()
        {
            // Check if delegate is assigned
            if (ServerStart != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = ServerStart.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(ServerStart, new object[] { });
                }
                else
                {
                    // Raise the event
                    ServerStart.Invoke();
                }
            }
        }
        private void RaiseAuthenticationMessageReceivedEvent(TCPServerMember sender, TCPServerMemberCredentials e)
        {
            // Check if delegate is assigned
            if (AuthenticationMessageReceived != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = AuthenticationMessageReceived.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(AuthenticationMessageReceived, new object[] { sender, e });
                }
                else
                {
                    // Raise the event
                    AuthenticationMessageReceived.Invoke(sender, e);
                }
            }
        }
        private void RaiseMessageReceivedEvent(TCPServerMember sender, string Message)
        {
            // Check if delegate is assigned
            if (MessageReceived != null)
            {
                // Check invoke status
                ISynchronizeInvoke syncInvoke = MessageReceived.Target as ISynchronizeInvoke;
                if (syncInvoke != null && syncInvoke.InvokeRequired)
                {
                    // Invokie the event on the main thread
                    syncInvoke.Invoke(MessageReceived, new object[] { sender, Message });
                }
                else
                {
                    // Raise the event
                    MessageReceived.Invoke(sender, Message);
                }
            }
        }
        #endregion

        #region Private Methods
        private void WaitForConnectionRequests()
        {
            // Listen incoming connections
            tlsServer.BeginAcceptTcpClient(new AsyncCallback(AcceptConnectionRequest), tlsServer);
        }
        private void AcceptConnectionRequest(IAsyncResult iar)
        {
            // Accept connection
            try
            {
                // End Accept TCP Client
                tclServer = tlsServer.EndAcceptTcpClient(iar);
                // Set No Delay
                tclServer.NoDelay = true;

                tclServer.ReceiveBufferSize = 1024;
                tclServer.SendBufferSize = 1024;
                tclServer.Client.NoDelay = true;
                tclServer.Client.ReceiveBufferSize = 1024;
                tclServer.Client.SendBufferSize = 1024;

                // Get Stream
                NetworkStream nstServer = tclServer.GetStream();
                // Get ip end point
                IPEndPoint ipaMember = (IPEndPoint)tclServer.Client.RemoteEndPoint;
                // Create new TCPServerMember 
                TCPServerMember tsmMember = new TCPServerMember();
                tsmMember.NetworkStream = nstServer;
                // Get Hash Code for tsmMember
                int intMemberHashCode = tsmMember.GetHashCode();
                // Add server member to hashtable
                this.hshMembers.Add(intMemberHashCode, tsmMember);
                // Assign authentication timeout
                ((TCPServerMember)this.hshMembers[intMemberHashCode]).AuthenticationTimeout = this.AuthenticationTimeout;
                // Assign TCPServerMember NetworkStream
                ((TCPServerMember)this.hshMembers[intMemberHashCode]).NetworkStream = nstServer;
                // Assign ip end point information to member
                ((TCPServerMember)this.hshMembers[intMemberHashCode]).MemberIPEndPoint = ipaMember;
                // Register for AuthenticationMessageReceived event
                ((TCPServerMember)this.hshMembers[intMemberHashCode]).AuthenticationMessageReceived += new TCPServerMember.MemberAuthenticationMessageReceivedDelegate(TCPServer_AuthenticationMessageReceived);
                // Register for MessageReceived event
                ((TCPServerMember)this.hshMembers[intMemberHashCode]).MessageReceived += new TCPServerMember.MemberMessageDelegate(TCPServer_MessageReceived);
                // Register for ConnectionTerminated event
                ((TCPServerMember)this.hshMembers[intMemberHashCode]).ConnectionTerminated += new TCPServerMember.ConnectionTerminatedDelegate(TCPServer_ConnectionTerminated);
                // Set client to wait for messages
                ((TCPServerMember)this.hshMembers[intMemberHashCode]).WaitForMessages();
                // Raise Connection Established Delegate
                this.RaiseConnectionEstablishedEvent((TCPServerMember)this.hshMembers[intMemberHashCode]);
                //this.ConnectionEstablished((TCPServerMember)this.hshMembers[intMemberHashCode]);
                // Continue listening incoming connections
                tlsServer.BeginAcceptTcpClient(new AsyncCallback(AcceptConnectionRequest), tlsServer);
            }
            catch (ObjectDisposedException odeExcp)
            {
                // Object disposed
                return;
            }
        }
        void TCPServer_ConnectionTerminated(TCPServerMember sender)
        {
            // Remove TCPServerMember from hashtable
            this.hshMembers.Remove(sender.GetHashCode());
            // Raise event
            this.RaiseConnectionTerminatedEvent(sender);
            //this.ConnectionTerminated(sender);
        }
        void TCPServer_MessageReceived(TCPServerMember sender, string Message)
        {
            // Raise event
            this.RaiseMessageReceivedEvent(sender, Message);
            //this.MessageReceived(sender, Message);
        }
        void TCPServer_AuthenticationMessageReceived(TCPServerMember sender, TCPServerMemberCredentials e)
        {
            // Raise event
            this.RaiseAuthenticationMessageReceivedEvent(sender, e);
            //this.AuthenticationMessageReceived(sender, e);
        }
        #endregion

        #region Public Methods
        public bool StartServer()
        {
            // Stop Server
            this.StopServer();
            try
            {
                // Create TCP Listener
                tlsServer = new TcpListener(
                    this.ServerIPAddress,
                    this.ServerPort
                    );
                // Start Listening
                tlsServer.Start();
            }
            catch
            {
                // Server did not start
                return false;
            }
            // Wait for connection Requests
            this.WaitForConnectionRequests();
            // Raise Server Started event
            this.RaiseServerStartEvent();
            //this.ServerStart();
            // Return True
            return true;
        }
        public bool StopServer()
        {
            // Set return value
            bool RetVal = true;
            // Close connections for TCPServerMembers
            int[] intMembers = TCPServerHelper.GetMemberHashCodes(ref this.hshMembers);
            foreach (int intMember in intMembers)
            {
                // Disconnect TCPServerMember instance
                ((TCPServerMember)this.hshMembers[intMember]).Disconnect();
            }
            // Clear hashtable
            this.hshMembers.Clear();
            // Stop TCP Listener
            try
            {
                if (tlsServer != null)
                {
                    tlsServer.Stop();
                }
            }
            catch
            {
                // Set return value
                RetVal = false;
            }
            // Stop TCP Client
            if (tclServer != null)
            {
                if (tclServer.Connected)
                {
                    tclServer.Close();
                }
            }
            // Raise Server Stop Event
            this.RaiseServerStopEvent();
            //this.ServerStop();
            // Return
            return RetVal;
        }
        #endregion

        #region IDisposable Members
        public void Dispose()
        {
            try
            {
                // Dispose TCPServerMembers
                int[] intMembers = TCPServerHelper.GetMemberHashCodes(ref this.hshMembers);
                foreach (int intMember in intMembers)
                {
                    // Dispose TCPServerMember instance
                    ((TCPServerMember)this.hshMembers[intMember]).Dispose();
                }
                // Clear hashtable
                this.hshMembers.Clear();
                // Close open connections
                this.StopServer();
            }
            catch
            {
            }
        }
        #endregion
    }
}
